/*
* ============================================================================
*  Name        : sea_atomic_op.h
*  Part of     : Finite state machine utilities
*  Description : object definition
*  Version     : %version: %
*  
*
* ============================================================================
*/
#if !defined( __sea_atomic_op_h__ )
#define __sea_atomic_op_h__

#include "sea_config.h"
#include "sea_defines.h"
#include "sea_types.h"

#if defined( SEA_OS_QT )
    #include <QAtomicInt>
#endif

/**
 * @file sea_atomic_op.h
 * @brief @ref sea::OsAtomic
 *
 * @ingroup Platforms
 */

namespace sea
{
#if defined( SEA_OS_WIN32 )
    typedef long OsAtomicInt;
#elif defined( SEA_OS_QT )
    typedef QAtomicInt OsAtomicInt;
#else
    typedef int OsAtomicInt;
#endif

    /**
     * @class OsAtomic
     * @brief Atomic increment/decrement
     *
     * @ingroup Platforms
     */
    class OsAtomic
    {
    public:
        OsAtomic( int value = 0 ) : m_value( value ) { }
        OsAtomic( OsAtomic& value ) { set( value.get( ) ); }

        /**
         * Atomic increment
         * @param value atomic value
         *
         * @return resulting value
         */
        int inc( int value = 1 );

        /**
         * Atomic increment
         *
         * @return resulting value
         */
        int operator++( ){ return inc( 1 ); }
        int operator++( int ){ return inc( 1 ); }

        /**
         * Atomic decrement
         *
         * @param value atomic value
         *
         * @return resulting value
         */
        int dec( int value = 1 );

        /**
         * Atomic decrement
         *
         * @return resulting value
         */
        int operator--( ){ return dec( 1 ); }
        int operator--( int ){ return dec( 1 ); }

        /**
         * Get integer value
         *
         * @return current integer value
         */
        int get( );

        /**
         * Atomic set 
         * @param value new value
         *
         * @return old value
         */
        int set( int value );

        /**
         * Get integer value
         *
         * @return current integer value
         */
        int operator*( ){ return get( ); }

        /**
         * Atomic compare and set if comparison is true
         *
         * @param value new value
         * @param expected_value  value to compare with
         *
         * @return old value, if comparison is true
         */
        int compare_set( int expected_value, int value );

        /**
         * Compare operator
         *
         * @return current integer value
         */
        bool operator==( int compare ) { return compare_set( compare, compare ) == compare; }

        /**
         * Compare operator
         *
         * @return current integer value
         */
        bool operator!=( int compare ) { return compare_set( compare, compare ) != compare; }

        /**
         * Assignment operator
         *
         * @return current integer value
         */
        int operator=( int new_value ) { return set( new_value ); }


    private:
        OsAtomicInt m_value;
    };
}

#endif
